import { defineStore } from 'pinia'
import device from 'current-device'
import {
  AppAuthProvider,
  firebaseAuth,
  firebaseLogin,
  firebaseSignOut,
  onAppCheckTokenChanged
} from '@/service/firebase'
import { computed, ref, watch } from 'vue'
import { api } from '@/service/net/server-api'

/**
 * 持久化KEY
 */
const persistenceKey = 'user_auth_info'

export const useAuthStore = defineStore('user-auth', () => {
  const state = ref<UserState>(initAuthInfoFromLocalStorage())
  // 监听变化并持久化到LocalStorage
  watch(state.value, value => {
    localStorage.setItem(persistenceKey, JSON.stringify(value))
  }, { deep: true })
  firebaseAuth.onAuthStateChanged(async (user) => {
    if (user && state.value.userInfo) {
      const idToken = await user.getIdToken()
      const uid = user.uid
      state.value.userInfo.idToken = idToken
      state.value.userInfo.uid = uid
    }
  })
  onAppCheckTokenChanged(appCheckToken => {
    state.value.appCheckToken = appCheckToken
  })

  function $reset() {
    state.value = {}
  }

  /**
   * 是否已登录授权
   */
  const isAuthorized = computed(() => state.value.userInfo?.uid != null)

  /**
   * 登录
   * @param provider 登录方式
   */
  async function signIn(provider: AppAuthProvider) {
    const isPopup = device.desktop() || import.meta.env.DEV
    const result = await firebaseLogin(provider, true, isPopup)
    const uid = result.userCredential.user.uid
    const idToken = await result.userCredential.user.getIdToken()
    if (!idToken) throw 'idToken is null'

    // 向服务器注册用户
    // Fixme(orange): uuid需要重新处理，如果不需要这个值直接删除
    const uuid = await api.createUser(uid, idToken)

    state.value.userInfo = { idToken: idToken, uid: uid, uuid: uuid }
  }

  /**
   * 退出登录
   */
  async function signOut() {
    await firebaseSignOut()
    $reset()
  }

  return { state, isAuthorized, signIn, signOut }
})

/**
 * 从LocalStorage获取授权信息
 */
function initAuthInfoFromLocalStorage(): UserState {
  try {
    const rawAuthInfo = localStorage.getItem(persistenceKey)
    return rawAuthInfo ? JSON.parse(rawAuthInfo) : {}
  } catch (e) {
    return {}
  }
}

interface UserState {
  appCheckToken?: string | null
  userInfo?: UserInfo | null
}

interface UserInfo {
  idToken: string | null
  uid: string | null
  uuid: string | null
}